import json
import time
from decimal import Decimal, getcontext

from django.http import HttpResponse
from django.conf import settings

from ...models.chat_product import ChatProduct
from ...models.users import Users
from ...models.chat_orders import ChatOrders

from ...utils.data_handle import new_snowflake_id, gen_qrcode
from .utils.wechatpay_handler import wechatpay, wxpay_notify, chaeck_wxpay_trade, payment_success
from .utils.alipay_handler import alipay_precreate, alipay_notify, chaeck_alipay_trade


def payways_list(request):
    '''
    获取支付方式
    '''
    data = {}

    if settings.WECHAT_PAY_CONFIG['Enabled']:
        data['payjs'] = {
            "name": "wechat"
        }

    if settings.ALI_PAY_CONFIG['Enabled']:
        data['alipay'] = {
            "name": "alipay"
        }

    res_mes = {
        "code": 0,
        "data": data
    }
    res_mes_json = json.dumps(res_mes, ensure_ascii=False)
    return HttpResponse(res_mes_json)


def payways_qrcode(request):
    '''
    PayQrcode 生成支付 URL 二维码
    POST
    body = {
        "pay_way": "payjs",
        "product_id": 1,
        "user_id": 3
    }
    '''
    if request.method == 'POST':
        json_b = request.body
        json_str = json_b.decode('utf-8')
        json_obj = json.loads(json_str)

        # 先查询产品信息
        try:
            product_id = json_obj['product_id']
            product_obj = ChatProduct.objects.get(id=product_id)
        except:
            res_mes = {
                "code": 1,
                "data": "未找到这个产品！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 生成一个唯一id
        orderno = new_snowflake_id()
        if not orderno:
            res_mes = {
                "code": 1,
                "data": "生成交易号时出错！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 查看用户id是否有效
        try:
            user_obj = Users.objects.get(id=json_obj['user_id'])
        except:
            res_mes = {
                "code": 1,
                "data": "用户ID无效！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 计算最后 需要支付的金额，因为涉及到钱，所以采用更精确的浮点数计算
        # 设置上下文精度为5，例如：符号，标度，小数点前的位数

        try:
            getcontext().prec = 2
            original_price = Decimal(str(product_obj.price))
            preferential_price = Decimal(str(product_obj.discount))

            final_price = original_price - preferential_price
        except:
            res_mes = {
                "code": 1,
                "data": "金额计算失败！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 创建订单信息，存储到数据库
        # 创建订单备注字典数据
        order_remark = {
            "days": product_obj.days,
            "power": product_obj.power,
            "name": product_obj.name,
            "price": product_obj.price,
            "discount": product_obj.discount
        }

        # 创建订单
        chat_orders_obj = ChatOrders(
            user_id = user_obj.id,
            username = user_obj.username,
            product_id = product_id,
            order_no = orderno,
            subject = product_obj.name,
            amount = final_price,
            status = 0,
            pay_way = json_obj['pay_way'],
            remark = order_remark
        )

        try:
            chat_orders_obj.save()
        except:
            res_mes = {
                "code": 1,
                "data": "订单创建失败！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)

        # 获取支付二维码
        '''
        {'code': 400, 'message': '{"code":"PARAM_ERROR","detail":{"location":"body","value":"0.01"},"message":"无法将 JSON 输入源“/body/amount/total”映射到目标字段“总金额”中，此字段需要一个合法的 64 位有符号整数"}'}
        {'code': 400, 'message': '{"code":"PARAM_ERROR","detail":{"location":"body","value":0},"message":"输入源“/body/amount/total”映射到数值字段“总金额”规则校验失败，值低于最小值 1"}'}
        {'code': 403, 'message': '{"code":"NO_AUTH","message":"此商家的收款功能已被限制，暂无法支付。商家可登录微信商户平台/微信支付商家助手小程序/经营账户页面查看原因和解决方案。"}'}
        '''

        # 判断是微信支付还是支付宝
        if json_obj['pay_way'] == "payjs":
            get_qrcode = wechatpay(final_price, orderno, product_obj.name)
        elif json_obj['pay_way'] == "alipay":
            get_qrcode = alipay_precreate(final_price, orderno, product_obj.name)
        else:
            res_mes = {
                "code": 1,
                "data": "支付方式 不支持！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)

        '''
        res_mes = {
            'code': 200,
            'message': code_url_str
        }
        '''

        if get_qrcode['code'] == 200:
            # 把code_url转换为二维码图片 并且是base64的二维码
            base_img = gen_qrcode(get_qrcode['message'])
            # base_img = "sad"
            if base_img:
                res_mes = {
                    "code": 0,
                    "data": {
                        "order_no": orderno,
                        "image": base_img
                        # "image": ""
                    }
                }
                res_mes_json = json.dumps(res_mes, ensure_ascii=False)
                return HttpResponse(res_mes_json)
            else:
                res_mes = {
                    "code": 1,
                    "message": "二维码生成失败！"
                }
                res_mes_json = json.dumps(res_mes, ensure_ascii=False)
                return HttpResponse(res_mes_json)
        else:
            res_mes = {
                "code": 1,
                "message": get_qrcode['message']
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)


def payways_wxpay_notify(request):
    '''
    微信支付 回调通知地址
    '''
    if request.method == 'POST':

        # {'code': 'SUCCESS', 'message': '成功'}
        # {'code': 'FAILED', 'message': '失败'}
        res = wxpay_notify(request)

        if res['code'] == "SUCCESS":
            res_mes = {
                "code": "SUCCESS",
                "message": "接收成功！"
            }
            return HttpResponse(res_mes, status=200, content_type='application/json')
        else:
            res_mes = {  
                "code": "FAIL",
                "message": "接收失败"
            }
            return HttpResponse(res_mes, status=500, content_type='application/json')


def payways_alipay_notify(request):
    '''
    支付宝支付 回调通知地址
    '''
    # 支付宝支付回调 数据
    if request.method == 'POST':
        # json_b = request.body
        # print(json_b, "原始")
        # json_str = json_b.decode('utf-8')
        # print(json_str, "code")
        # json_obj = json.loads(json_str)

        post_data = request.POST.dict()  # 将POST数据转换为字典
        # print(post_data, "打印所有POST参数")  # 打印所有POST参数

        res = alipay_notify(post_data)

        if res['code'] == "SUCCESS":
            # res_mes = {
            #     "code": "success",
            #     "message": "接收成功！"
            # }
            # return HttpResponse(res_mes, status=200, content_type='application/json')
            return HttpResponse("success", status=200)
        else:
            # res_mes = {
            #     "code": "fail",
            #     "message": "接收失败"
            # }
            # return HttpResponse(res_mes, status=500, content_type='application/json')
            return HttpResponse("fail", status=500)


def payways_query(request):
    '''
    查询订单状态
    order_no
    '''
    if request.method == 'POST':
        json_b = request.body
        json_str = json_b.decode('utf-8')
        json_obj = json.loads(json_str)

        chatorder_obj = ChatOrders.objects.filter(order_no=json_obj['order_no'])

        if chatorder_obj:
            if chatorder_obj[0].status == 2:
                res_mes = {
                    "code": 0,
                    "data": {
                        "status": chatorder_obj.status
                    }
                }
                res_mes_json = json.dumps(res_mes, ensure_ascii=False)
                return HttpResponse(res_mes_json)
            
            # 循环查询订单状态，循环15秒，每一秒查询一次
            for i in range(15):
                # 在这里执行你的代码
                time.sleep(1)  # 等待1秒

                chatorder_obj = ChatOrders.objects.get(order_no=json_obj['order_no'])
                if chatorder_obj.status == 2:
                    res_mes = {
                        "code": 0,
                        "data": {
                            "status": chatorder_obj.status
                            }
                        }
                    res_mes_json = json.dumps(res_mes, ensure_ascii=False)
                    return HttpResponse(res_mes_json)
            
            # 如果要是数据库 自己平台这边的数据一直不更新 就直接去微信支付平台查询订单是否支付完成
            # 因为用户付款后 要是不点击完成 微信支付那边就不会 回调通知接口，这样的话就不知道这个订单的状态
            # 所以需要主动的 去查询一下这个订单的状态
            if chatorder_obj.pay_way == "payjs": # 微信
                chaeck_trade_res = chaeck_wxpay_trade(json_obj['order_no'])
            else: # 支付宝
                chaeck_trade_res = chaeck_alipay_trade(json_obj['order_no'])

            # 如果订单不是完成的状态 会返回error字符串
            if not chaeck_trade_res:
                # 如果订单支付成功了 那么就去更新数据库
                res = payment_success(json_obj['order_no'])

                if not res:
                    # 如果更新用户算力 或者检查一些东西 没有问题 那就判断这个订单是完成状态
                    res_mes = {
                        "code": 0,
                        "data": {
                            "status": 2
                        }
                    }
                    res_mes_json = json.dumps(res_mes, ensure_ascii=False)
                    return HttpResponse(res_mes_json)
            else:
                res_mes = {
                    "code": 0,
                    "data": {
                        "status": chatorder_obj.status
                    }
                }
                res_mes_json = json.dumps(res_mes, ensure_ascii=False)
                return HttpResponse(res_mes_json)

        else:
            res_mes = {
                "code": 1,
                "message": "没有这个订单！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)

